package com.alinks.modbus.core.frame;

import com.alinks.modbus.core.exception.ModbusSlaveCodeEnum;
import com.alinks.modbus.core.utils.ASCIIUtil;
import com.alinks.modbus.core.utils.CRC16;
import com.alinks.modbus.core.utils.LRC;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

public class ASCIIFrame extends ModbusFrame {

    public final static String PREFX = "3A";
    public final static String SUFFIX = "DA";
    /**
     *    +-------------------------------------------------+
     *          |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
     * +--------+-------------------------------------------------+----------------+
     * |00000000| 3a 30 31 30 33 30 30 30 30 30 30 30 41 46 32 0d |:01030000000AF2.|
     * |00000010| 0a                                              |.               |
     * +--------+-------------------------------------------------+----------------+
     *
     * :+Header + 协议格式+CRC+.
     */

    @Setter
    @Getter
    @Builder
    public static class Request extends ModbusFrame {

        /**
         * 前缀:
         */
        private byte prefix;
        /**
         * MBAP header 报文头
         */
        private Header header;

        private RequestBody body;

        private byte lrc;

        /**
         * 后缀.
         */
        private byte suffix1;
        private byte suffix2;

        private Except except;

        public void check() {
            if (body == null) {
                TcpFrame.Except except = TcpFrame.Except.builder()
                        .func((byte)(body.getFunc() | 0x80))
                        .exceptCode(ModbusSlaveCodeEnum.EXCEPT_01)
                        .build();
                this.except = except;
            } else {
                byte[] readBytes = new byte[getReadLength()];
                readBytes[0] = ((ASCIIFrame.ASCIIHeader)header).unitId;
                body.getbodyBytes(readBytes, 0);
                //0x01,0x03, 0x00, 0x00, 0x00, 0x0a
                byte calcLrc= (byte)(LRC.calc(readBytes) & 0xff);
                if (calcLrc != lrc) {
                    TcpFrame.Except except = TcpFrame.Except.builder()
                            .func((byte)(body.getFunc() | 0x80))
                            .exceptCode(ModbusSlaveCodeEnum.EXCEPT_03)
                            .build();
                    this.except = except;
                }
            }
        }

    }

    @Setter
    @Getter
    @Builder
    public static class Response extends ModbusFrame {
        /**
         * 前缀:
         */
        private byte prefix;
        /**
         * MBAP header 报文头
         */
        private Header header;

        private ResponseBody body;

        private byte lrc;

        /**
         * 后缀.
         */
        private byte suffix1;
        private byte suffix2;

        private Except except;


    }

    @Setter
    @Getter
    @Builder
    public static class ASCIIHeader extends Header {
        /**
         * 单元标识
         */
        protected byte unitId;

        /**
         * 获取头字节数组
         * @return
         */
        @Override
        public byte[] getHeaderBytes() {
            return new byte[]{
                    ASCIIUtil.byteAsciiToByte((byte)(unitId >> 4 & 0xf)),
                    ASCIIUtil.byteAsciiToByte((byte)(unitId & 0xf))
            };
        }
    }
}
